from WiFi import protocol
import threading
import queue
import socket
import time

data_len_min = 17       #最小消息长度
data_len_max = 1041     #最大消息长度

#============================#
#   接收到的数据
#============================#
class RecvData:
    
    def __init__(self,max_len=0,tim=0):
        self.tim = tim
        self.num = None         #存消息包的完整数据长度
        self.fec_num = None     #存消息冗余包的完整数据长度
        self.max_len = max_len  #存消息包的单个片段的最大数据长度
        self.msg_id = None      #数据ID
        self.cnt = 0            #接收计算
        self.fec_cnt = 0        #冗余包计算
        self.packs = {}         #存储数据片段
        self.fec_packs = {}     #存储数据冗余包
        self.t = time.time()    #存储接收时间

#============================#
#   接收数据
#============================#
class Recver:

    #----------------------#
    #   初始化接收器
    #----------------------#
    def __init__(self,sock):
        self.run = False                        #线程运行标志
        self.sock = sock                        #网络端口

        self.msg_buffer = {}                    #完整消息
        for i in range(0,127):                  #初始化完整信息队列（127个）
            self.msg_buffer[i] = queue.Queue(2) 

        self.data_temp = {}                     #消息片段
        for i in range(0,255):                  #初始化消息片段
            self. data_temp[i] = {}             
        self.rxStart()

    #----------------------#
    #   开始接收
    #----------------------#
    def rxStart(self):
        if self.run == True:
            return
        print('开始接收wifi数据')
        self.recvThread = threading.Thread(target=self.recvLoop)
        self.clearThread = threading.Thread(target=self.clearLoop)
        self.run = True
        self.recvThread.start()
        self.clearThread.start()

    #----------------------#
    #   手动停止接收
    #----------------------#
    def rxStop(self):
        self.run = False
        time.sleep(1)
    
    #----------------------#
    #   接收、过滤消息线程
    #----------------------#
    def recvLoop(self):
        while self.run:
            data,_ = self.sock.recvfrom(65535)  #从网络端口中接收数据
            l = len(data)                                                   #获取数据长度
            if( l < data_len_min or l > data_len_max ):                     #判断是否在规定长度范围内
                print('不在规定长度范围内')
                continue
            ret,TIM,LEN,NUM,SEQ,SYS,MSG,PAYLOAD = protocol.decodePack(data) #数据解包
            #print(ret)
            try:
                if(ret == True):                                                #解包成功
                    #print('get tim = ',TIM)
                    if( not TIM in self.data_temp[SYS].keys() ):                #如果之序号为TIM的数据包没有接收到
                        self.data_temp[SYS][TIM] = RecvData(max_len = LEN,tim=TIM)#创建数据接收缓冲
                    #print('msg id = ',MSG)
                    #--------------------------------------------------------------------------------------------#
                    if(MSG < 128):                                              #本次接收到的是数据片段
                        if(self.data_temp[SYS][TIM].num == None):               #第一次接收到数据包时的一些初始化
                            self.data_temp[SYS][TIM].num = NUM                  #记录数据包长度
                            for i in range(0,NUM):                              #初始化数据包缓冲
                                self.data_temp[SYS][TIM].packs[i] = None

                        self.data_temp[SYS][TIM].packs[SEQ] = PAYLOAD           #存储数据片段
                        self.data_temp[SYS][TIM].cnt += 1                       #数据接收计数
                        if(self.data_temp[SYS][TIM].max_len < LEN):             #防止之前接收到的是最末尾的数据包
                            self.data_temp[SYS][TIM].max_len = LEN
                        #print('save pack')
                    #--------------------------------------------------------------------------------------------#
                    else:                                                       #本次接收到的是冗余包
                        if(self.data_temp[SYS][TIM].fec_num == None):           #第一次接收到冗余包时的一些初始化
                            self.data_temp[SYS][TIM].fec_num = NUM              #记录冗余包长度
                            for i in range(0,NUM):                              #初始化冗余包缓冲
                                self.data_temp[SYS][TIM].fec_packs[i] = None

                        self.data_temp[SYS][TIM].fec_packs[SEQ] = PAYLOAD       #存储冗余包
                        #print('save fec pack')
                        self.data_temp[SYS][TIM].fec_cnt += 1                   #冗余包接收计数
                    #--------------------------------------------------------------------------------------------#
                    self.data_temp[SYS][TIM].t = time.time()                    #刷新最后一次数据的时间
                    if( (self.data_temp[SYS][TIM].cnt + self.data_temp[SYS][TIM].fec_cnt) >= NUM):#可能接收完成
                        print(self.data_temp[SYS][TIM].cnt , '  ', self.data_temp[SYS][TIM].fec_cnt)
                        data = protocol.decodeFEC( self.data_temp[SYS][TIM].packs,                #尝试还原数据
                                                   self.data_temp[SYS][TIM].fec_packs, 
                                                   self.data_temp[SYS][TIM].num, 
                                                   self.data_temp[SYS][TIM].max_len)
                        if( data == None):  #还原失败
                            #print('还原失败')
                            continue
                        #print('还原成功')
                        if(MSG<128):
                            if(self.msg_buffer[MSG].full()):
                                try:    self.msg_buffer[MSG].get(timeout=0.001)     #之前的数据还没取出来，队列满了
                                except: pass
                            self.msg_buffer[MSG].put(data,False)                    #把数据放到对应的队列中
                        else:
                            if(self.msg_buffer[255-MSG].full()):
                                try:    self.msg_buffer[255-MSG].get(timeout=0.001)     #之前的数据还没取出来，队列满了
                                except: pass
                            self.msg_buffer[255-MSG].put(data,False)                    #把数据放到对应的队列中
                        del(self.data_temp[SYS][TIM])                           #释放内存
                #else:
                    #print('解包失败')
            except:
                print('过滤线程产生了一个错误')

    #----------------------#
    #   清理缓存线程
    #----------------------#
    def clearLoop(self):
        while self.run:
            time.sleep(0.1)
            t = time.time()
            try:
                for sys in range(len(self.data_temp)):  #按系统ID取
                    #print(len(self.data_temp[sys]))
                    for tim in self.data_temp[sys]:#这个ID下，按时间刻度取
                        #print('tim = ',temp_tim)
                        if((t - self.data_temp[sys][tim].t) > 0.1):     #超过一定时间没有反应的缓冲需要删除掉
                            del(self.data_temp[sys][tim])
                            #print('清除一次',sys,',缓存剩余:',len(self.data_temp[sys]))
            except:
                #self.run = False
                #print('clear error')
                pass
            
